import axios, {
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
  type InternalAxiosRequestConfig
} from 'axios'
import { notification } from 'antd'

type ResponseType<T> = {
  code: number
  msg: string
  data: T
  timestamp: string
}

class Request {
  private instance: AxiosInstance

  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create(config)

    this.interceptors()
  }

  private interceptors(): void {
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        console.log(config)
        const token = sessionStorage.getItem('token')
        if (token) {
          config.headers['Authorization'] = token
        }

        return config
      },
      (err) => {
        return Promise.reject(err)
      }
    )
    this.instance.interceptors.response.use(
      (res: AxiosResponse) => {
        if (res.status >= 200 && res.status < 300) {
          if (res.headers['content-type'] === 'application/octet-stream') {
            return res.data
          }
          if (res.data.code === 200) {
            return res.data
          }
        }
        notification.error({
          message: res.data.msg,
          duration: 10,
          showProgress: true
        })
        return Promise.reject(res.data)
      },
      (err) => {
        console.log(err)
        return Promise.reject(err)
      }
    )
  }

  public get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<ResponseType<T>> {
    return this.instance.get(url, config)
  }
  public post<T = unknown>(
    url: string,
    data?: unknown,
    config?: AxiosRequestConfig
  ): Promise<ResponseType<T>> {
    return this.instance.post(url, data, config)
  }
  public put<T = unknown>(
    url: string,
    data?: unknown,
    config?: AxiosRequestConfig
  ): Promise<ResponseType<T>> {
    return this.instance.put(url, data, config)
  }
  public delete<T = unknown>(url: string, params?: unknown): Promise<ResponseType<T>> {
    return this.instance.delete(url, { params })
  }
  public download(url: string, params?: unknown): Promise<Blob> {
    return this.instance.get(url, { params, responseType: 'blob' })
  }
}

const httpRequest = new Request({
  baseURL: 'http://localhost:3000'
})

export default httpRequest
